/**
 *	@file	bc_use_3d.c
 *	@brief	ボンジュース使用演出画面　3D関連
 *	@author	Miyuki iwasawa
 *	@date	06.03.28
 */

#include "common.h"
#include "system/procsys.h"
#include "system/clact_tool.h"
#include "system/wordset.h"
#include "system/numfont.h"
#include "system/softsprite.h"
#include "poketool/monsno.h"

#include "bc_use_3d.h"
#include "wazaeffect/we_def.h"

#define POKEA_INI_PX	(25*8+4)	///<デモポケモン初期座標X
#define POKEA_INI_PY	(14*8)	///<デモポケモン初期座標Y
#define PARTICLE_CAMERA_NEAR		(FX32_ONE)			///< カメラ
#define PARTICLE_CAMERA_FAR		(FX32_ONE * 900)

#define PARTICLE_OX	(POKEA_INI_PX-128)
#define PARTICLE_OY	(-24)

#include "bong_use_gra.naix"

//======================================================
//プロトタイプ
//======================================================
static void sub_3DVramInit(void);
static void sub_3DParamInit(void);
static u32 cb_ParticleAllocTex(u32 size, BOOL is4x4comp);
static u32 cb_ParticleAllocTexPalette(u32 size, BOOL is4pltt);
static void cb_EmitterSetup(EMIT_PTR emit);
static PTC_PTR sub_ParticleSystemInit(int heapID);
static void sub_ParticleInit(BC_USE_3D* wk);
static void sub_ParticleRelease(BC_USE_3D* wk);

static void sub_CameraInit(BC_USE_3D* wk,int heapID);
static void sub_SoftSpriteInit(BC_USE_3D* wk,BC_USE_POKE* poke,int heapID);


/**
 *	@brief	3D関連初期化
 */
BC_USE_3D* BongUse3D_Init(int heapID)
{
	BC_USE_3D* wk = sys_AllocMemory(heapID,sizeof(BC_USE_3D));

	MI_CpuClear8(wk,sizeof(BC_USE_3D));

	wk->heapID = heapID;

	//マネージャー初期化
	wk->man = GF_G3DMAN_Init(heapID,
			GF_G3DMAN_LNK,GF_G3DTEX_256K,
			GF_G3DMAN_LNK,GF_G3DPLT_16K,sub_3DParamInit);

	sub_3DVramInit();

	//カメラ初期化
	sub_CameraInit(wk,heapID);

	//パーティクル初期化
	sub_ParticleInit(wk);

	//ソフトウェアスプライト初期化
	wk->ssm = SoftSpriteInit(heapID);

	GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG0, VISIBLE_ON );
    G2_SetBG0Priority(1);

	return wk;
}

/**
 *	@brief	ボンジュース使用シーケンス3D　3Dメイン
 */
void BongUse3D_Main(BC_USE_3D* wk)
{
	GF_G3X_Reset();

	Particle_DrawAll();

	GF_G3X_Reset();
	NNS_G2dSetupSoftwareSpriteCamera();
	GFC_CameraLookAt();

	G3_MtxMode( GX_MTXMODE_PROJECTION );
	G3_Identity();
	G3_MtxMode( GX_MTXMODE_POSITION_VECTOR );
	G3_Identity();

	NNS_G3dGlbFlush();
	NNS_G2dSetupSoftwareSpriteCamera();
	SoftSpriteMain( wk->ssm );

	Particle_CalcAll();

	G3_SwapBuffers( GX_SORTMODE_MANUAL, GX_BUFFERMODE_Z );
}

/**
 *	@brief	ボンジュース使用シーケンス3D　3Dリソース解放
 */
void BongUse3D_Release(BC_USE_3D* wk)
{
	GFC_FreeCamera(wk->camera);
	SoftSpriteEnd(wk->ssm);

	//パーティクル解放
	sub_ParticleRelease(wk);

	GF_G3D_Exit( wk->man );	//3dマネージャー解放
	sys_FreeMemoryEz(wk);
}

/**
 *	@brief	ボンジュース使用シーケンス 3D VBlank処理
 */
void BongUse3D_VBlank(BC_USE_3D* wk)
{
	SoftSpriteTextureTrans( wk->ssm );
}

/**
 *	@brief	ソフトウェアスプライト追加
 */
void BongUse3D_PokeAdd(BC_USE_3D* wk,BC_USE_POKE* poke)
{
	SOFT_SPRITE_ARC	ssa;
	SOFT_SPRITE	* ss;

	PokeGraArcDataGetPP( &ssa,poke->pp,PARA_FRONT);

	ss = SoftSpriteAdd( wk->ssm, &ssa,POKEA_INI_PX,POKEA_INI_PY, 0, 0, NULL, NULL );
//	SoftSpriteParaSet( ss, SS_PARA_H_FLIP,poke->flip);
	wk->ss = ss;
}

/**
 *	@brief	ソフトウェアスプライト削除
 */
void BongUse3D_PokeDel(BC_USE_3D* wk)
{
	if(wk->ss == NULL){
		return;
	}
	SoftSpriteDel( wk->ss );
	wk->ss = NULL;
}

/**
 *	@brief	エミッタ生成
 */
void BongUse3D_ParticleEmitterAdd(BC_USE_3D* wk,int spr_id)
{
	Particle_CreateEmitterCallback(wk->ptc, spr_id, cb_EmitterSetup, wk);
	Particle_CameraTypeSet(wk->ptc, GF_CAMERA_ORTHO);
}

/**
 *	@brief	エミッタ稼動チェック
 */
BOOL BongUse3D_ParticleEmitterIsActive(BC_USE_3D* wk)
{
	if (Particle_GetEmitterNum(wk->ptc) == 0){
		return FALSE;
	}

	return TRUE;
}

/**
 *	@brief	3D初期化
 */
static void sub_3DParamInit(void)
{
	NNS_G3dInit();		// NitroSystem:３Ｄエンジンの初期化
	G3X_Init();
	G3X_InitMtxStack();
	G3X_SetShading( GX_SHADING_TOON );
	G3X_AlphaTest( FALSE, 0 );
	G3X_AlphaBlend( TRUE );
	G3X_AntiAlias( TRUE );
	G3X_EdgeMarking( FALSE );
	G3X_SetFog( FALSE, 0, 0, 0 );
	G3X_SetClearColor( 0, 0, 0x7fff, 63, FALSE );
	G3_SwapBuffers( GX_SORTMODE_AUTO, GX_BUFFERMODE_W );
	G3_ViewPort( 0, 0, 255, 191 );
}

/**
 *	@brief	3DVram初期化
 *
 *	ポケモンのソフトウェアスプライトが固定でVRAMの頭から領域を使うので
 *	その分の領域を一番最初に確保しておく。
 *	でないと、スプライトがその領域を上書きしてしまうので注意！
 */
static void sub_3DVramInit(void)
{
	NNSGfdTexKey tex_key;
	NNSGfdPlttKey pltt_key;

	tex_key		= NNS_GfdAllocTexVram(0x2000 * CLIENT_MAX, 0, 0);
	pltt_key	= NNS_GfdAllocPlttVram(0x20 *(CLIENT_MAX+1), 0, 0);

	GF_ASSERT(tex_key != NNS_GFD_ALLOC_ERROR_TEXKEY);
	GF_ASSERT(pltt_key != NNS_GFD_ALLOC_ERROR_PLTTKEY);

	Particle_SystemWorkInit();
}

//--------------------------------------------------------------
/**
 * @brief	領域確保
 *
 * @param	size
 * @param	is4x4comp
 *
 * @retval	static u32
 *
 */
//--------------------------------------------------------------
static u32 cb_ParticleAllocTex(u32 size, BOOL is4x4comp)
{
	NNSGfdTexKey key;
	u32 address;

	key = NNS_GfdAllocTexVram(size, is4x4comp, 0);
	Particle_LnkTexKeySet(key);		//リンクドリストを使用しているのでキー情報をセット

	address = NNS_GfdGetTexKeyAddr(key);
	OS_Printf("テクスチャVramアドレス＝%#x\n", address);
	return address;
}


//--------------------------------------------------------------
/**
 * @brief	領域確保
 *
 * @param	size
 * @param	is4pltt
 *
 * @retval	static u32
 *
 */
//--------------------------------------------------------------
static u32 cb_ParticleAllocTexPalette(u32 size, BOOL is4pltt)
{
	NNSGfdPlttKey key;
	u32 address;

	key = NNS_GfdAllocPlttVram(size, is4pltt, 0);
	Particle_PlttLnkTexKeySet(key);	//リンクドリストを使用しているのでキー情報をセット

	address = NNS_GfdGetPlttKeyAddr(key);
	return address;
}

//--------------------------------------------------------------
/**
 * @brief	エミッタ生成時コールバック
 *
 * @param	emit
 *
 * @retval	none
 *
 */
//--------------------------------------------------------------
static void cb_EmitterSetup(EMIT_PTR emit)
{
	VecFx32 pos = { 0, 0, 0 };

	VEC_Set(&pos, PT_LCD_PTP_CHG(PARTICLE_OX), PT_LCD_PTP_CHG(PARTICLE_OY), PT_LCD_PTP_CHG(-40));

	SPL_SetEmitterPosition(emit, &pos);
}

/**
 *	@brief	パーティクルシステム初期化
 */
static PTC_PTR sub_ParticleSystemInit(int heapID)
{
	PTC_PTR ptc;
	void *buf;
	GF_CAMERA_PTR camera_ptr;

	buf = sys_AllocMemory(heapID, PARTICLE_LIB_HEAP_SIZE);
	ptc = Particle_SystemCreate(cb_ParticleAllocTex, cb_ParticleAllocTexPalette,
			buf, PARTICLE_LIB_HEAP_SIZE, TRUE, heapID);

	camera_ptr = Particle_GetCameraPtr(ptc);
	if(camera_ptr != NULL){
		GFC_SetCameraClip(PARTICLE_CAMERA_NEAR, PARTICLE_CAMERA_FAR, camera_ptr);
	}
	return ptc;
}

/*
 *	@brief	パーティクル初期化
 */
static void sub_ParticleInit(BC_USE_3D* wk)
{
	void* res;

	//システム初期化
	wk->ptc = sub_ParticleSystemInit(wk->heapID);
	Particle_CameraTypeSet(wk->ptc, GF_CAMERA_ORTHO);

	//リソース確保
	res = Particle_ArcResourceLoad(ARC_BONG_USE_GRA, NARC_bong_use_gra_ptcl_bong_use_spa, wk->heapID);
	Particle_ResourceSet(wk->ptc, res, PTC_AUTOTEX_LNK | PTC_AUTOPLTT_LNK, TRUE);
}

/**
 *	@brief	パーティクル解放
 */
static void sub_ParticleRelease(BC_USE_3D* wk)
{
	Particle_SystemExit(wk->ptc);
	sys_FreeMemoryEz(wk->ptc);
}

/**
 *	@brief	ボンジュース使用シーケンス3D　カメラ設定
 */
static void sub_CameraInit(BC_USE_3D* wk,int heapID)		// カメラ
{
	VecFx32	camera_pos = {0,0,0x10000};
	CAMERA_ANGLE angle = {0,0,0};
	fx32	distance   = 0x10000;
	u16		perspway   = 0x05c1;

	wk->camera = GFC_AllocCamera(heapID);

	GFC_InitCameraCDA(&camera_pos,distance,&angle,perspway,GF_CAMERA_ORTHO,wk->camera);
	GFC_SetCameraClip(0,FX32_CONST(100),wk->camera);
	GFC_PurgeCameraTarget(wk->camera);
	GFC_AttachCamera(wk->camera);
}
